package org.elanfox.cloud.elasticsearch.config;

import org.elanfox.cloud.common.enums.base.CodeDescCommonEnum;
import org.elanfox.cloud.common.enums.base.CodeDescEnumHelper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.elasticsearch.core.ElasticsearchEntityMapper;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchCustomConversions;
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
import org.springframework.lang.Nullable;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Arrays;

/**
 * @author allan
 * @version 1.0.0
 * @date 2020/7/22
 */
@Configuration
public class EsConfig {
    @Bean
    public EntityMapper entityMapper(SimpleElasticsearchMappingContext context) {

        ElasticsearchEntityMapper entityMapper = new ElasticsearchEntityMapper(
                context, new DefaultConversionService()
        );
        ElasticsearchCustomConversions customConversions = new ElasticsearchCustomConversions(
                Arrays.asList(
                        LongToLocalDateTimeConverter.INSTANCE,
                        IntegerToEnumConverter.INSTANCE,
                        EnumToIntegerConverter.INSTANCE
                )
        );
        entityMapper.setConversions(customConversions);

        return entityMapper;
    }

    @ReadingConverter
    enum LongToLocalDateTimeConverter implements Converter<Long, LocalDateTime> {
        INSTANCE;

        LongToLocalDateTimeConverter() {
        }

        @Override
        @Nullable
        public LocalDateTime convert(Long source) {
            return Instant.ofEpochMilli(source).atZone(ZoneId.systemDefault()).toLocalDateTime();
        }
    }

    @ReadingConverter
    enum IntegerToEnumConverter implements Converter<Integer, CodeDescCommonEnum> {
        INSTANCE;

        IntegerToEnumConverter() {
        }

        @Override
        @Nullable
        public CodeDescCommonEnum convert(Integer source) {
            return CodeDescEnumHelper.getEnumTypeByCode(CodeDescCommonEnum.class, source);
        }
    }

    @WritingConverter
    enum EnumToIntegerConverter implements Converter<CodeDescCommonEnum, Integer> {
        INSTANCE;

        EnumToIntegerConverter() {

        }

        @Override
        @Nullable
        public Integer convert(CodeDescCommonEnum codeDescCommonEnum) {
            return (Integer) codeDescCommonEnum.getCode();
        }
    }
}
